<html>
<head>
    <meta charSet="utf-8">
    <title>BigFile-WebUploader</title>

    <link rel="stylesheet" href="/js/bootstrap.min.css">
    <link rel="stylesheet" href="/js/webuploader-0.1.5/webuploader.css">

    <script src="/js/jquery.min.js"></script>
    <script src="/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="/js/webuploader-0.1.5/webuploader.js"></script>

</head>
<body>

<div id="uploader" className="wu-example">

    <div id="thelist" className="uploader-list"></div>

    <div className="btns">
        <div id="picker">选择大文件</div>
        <button id="ctlBtn" className="btn btn-default">开始上传</button>
        <button id="stopBtn" className="btn btn-default">暂停</button>
        <button id="restart" className="btn btn-default">开始</button>
    </div>

</div>

</body>
<!--业务js文件-->
<script>
    var $btn = $('#ctlBtn');
    var $thelist = $('#thelist');
    var startDate;
    // HOOK 这个必须要再uploader实例化前面
    WebUploader.Uploader.register({
        // 在文件发送之前执行
        'before-send-file': 'beforeSendFile',
        // 在文件分片（如果没有启用分片，整个文件被当成一个分片）后，上传之前执行
        'before-send': 'beforeSend',
        // 在文件所有分片都上传完后，且服务端没有错误返回后执行
        "after-send-file": "afterSendFile"
    }, {
        beforeSendFile: function (file) {
            startDate = new Date();
            console.log("开始上传时间" + startDate)
            console.log("beforeSendFile");
            // Deferred对象在钩子回掉函数中经常要用到，用来处理需要等待的异步操作。
            var deferred = WebUploader.Deferred();
            //1、计算文件的唯一标记MD5，用于断点续传
            uploader.md5File(file, 0, 3 * 1024 * 1024).progress(function (percentage) {
                // 上传进度
                console.log('上传进度:', percentage);
                getProgressBar(file, percentage, "MD5", "MD5");
            }).then(function (val) { // 完成
                console.log('File MD5 Result:', val);
                file.md5 = val;
                file.uid = WebUploader.Base.guid();
                // 判断文件是否上传过，是否存在分片，断点续传
                $.ajax({
                    type: "POST",
                    url: "bigfile/check",
                    async: false,
                    data: {
                        fileMd5: val
                    },
                    success: function (data) {
                        var resultCode = data.resultCode;
                        // 秒传
                        if (resultCode == -1) {
                            // 文件已经上传过,忽略上传过程，直接标识上传成功；
                            uploader.skipFile(file);
                            file.pass = true;
                        } else {
                            //文件没有上传过，下标为0
                            //文件上传中断过，返回当前已经上传到的下标
                            file.indexcode = resultCode;
                        }
                    }, error: function () {

                    }
                });
                //获取文件信息后进入下一步
                deferred.resolve();
            });
            return deferred.promise();
        },
        beforeSend: function (block) {
            //获取已经上传过的下标
            var indexchunk = block.file.indexcode;
            var deferred = WebUploader.Deferred();
            if (indexchunk > 0) {
                if (block.chunk > indexchunk) {
                    //分块不存在，重新发送该分块内容
                    deferred.resolve();
                } else {
                    //分块存在，跳过
                    deferred.reject();
                }
            } else {
                //分块不存在，重新发送该分块内容
                deferred.resolve();
            }
            //返回Deferred的Promise对象。
            return deferred.promise();
        }
        , afterSendFile: function (file) {
            //如果所有分块上传成功，则通知后台合并分块
            $.ajax({
                type: "POST",
                url: "bigfile/merge",
                data: {
                    fileName: file.name,
                    fileMd5: file.md5
                },
                success: function (data) {

                }, error: function () {

                }
            });
        }
    });

    // 实例化
    var uploader = WebUploader.create({
        pick: {
            id: '#picker',
            label: '点击选择文件'
        },
        duplicate: true,//去重， 根据文件名字、文件大小和最后修改时间来生成hash Key
        swf: 'js/Uploader.swf',
        chunked: true,
        chunkSize: 10 * 1024 * 1024, // 10M 每个分片的大小限制
        threads: 3,
        server: 'bigfile/upload',
        auto: true,
        // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候，把图片打开。
        disableGlobalDnd: true,
        fileNumLimit: 1024,
        fileSizeLimit: 50 * 1024 * 1024 * 1024,//50G 验证文件总大小是否超出限制, 超出则不允许加入队列
        fileSingleSizeLimit: 10 * 1024 * 1024 * 1024 //10G 验证单个文件大小是否超出限制, 超出则不允许加入队列
    });

    // 当有文件被添加进队列的时候
    uploader.on('fileQueued', function (file) {
        $thelist.append('<div id="' + file.id + '" class="item">' +
            '<h4 class="info">' + file.name + '</h4>' +
            '<p class="state">等待上传...</p>' +
            '</div>');
        $("#stopBtn").click(function () {
            uploader.stop(true);
        });
        $("#restart").click(function () {
            uploader.upload(file);
        });
    });

    //当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。
    uploader.onUploadBeforeSend = function (obj, data) {
        //console.log("onUploadBeforeSend");
        var file = obj.file;
        data.md5 = file.md5 || '';
        data.uid = file.uid;
    };
    // 上传中
    uploader.on('uploadProgress', function (file, percentage) {
        getProgressBar(file, percentage, "FILE", "上传进度");
    });
    // 上传返回结果
    uploader.on('uploadSuccess', function (file) {
        var endDate = new Date();
        console.log("文件上传耗时:" + (endDate - startDate) / 1000 + "s")
        var text = '已上传';
        if (file.pass) {
            text = "文件妙传功能，文件已上传。"
        }
        $('#' + file.id).find('p.state').text(text);
    });
    uploader.on('uploadError', function (file) {
        $('#' + file.id).find('p.state').text('上传出错');
    });
    uploader.on('uploadComplete', function (file) {
        // 隐藏进度条
        fadeOutProgress(file, 'MD5');
        fadeOutProgress(file, 'FILE');
    });
    // 文件上传
    $btn.on('click', function () {
        uploader.upload();
    });

    /**
     *  生成进度条封装方法
     * @param file 文件
     * @param percentage 进度值
     * @param id_Prefix id前缀
     * @param titleName 标题名
     */
    function getProgressBar(file, percentage, id_Prefix, titleName) {
        var $li = $('#' + file.id), $percent = $li.find('#' + id_Prefix + '-progress-bar');
        // 避免重复创建
        if (!$percent.length) {
            $percent = $('<div id="' + id_Prefix + '-progress" class="progress progress-striped active">' +
                '<div id="' + id_Prefix + '-progress-bar" class="progress-bar" role="progressbar" style="width: 0%">' +
                '</div>' +
                '</div>'
            ).appendTo($li).find('#' + id_Prefix + '-progress-bar');
        }
        var progressPercentage = parseInt(percentage * 100) + '%';
        $percent.css('width', progressPercentage);
        $percent.html(titleName + ':' + progressPercentage);
    }


    /**
     * 隐藏进度条
     * @param file 文件对象
     * @param id_Prefix id前缀
     */
    function fadeOutProgress(file, id_Prefix) {
        $('#' + file.id).find('#' + id_Prefix + '-progress').fadeOut();
    }
</script>
</html>